using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Reflection;
using System.Collections;
using System.Windows.Forms;
using System.ComponentModel.Design;
using EnvDTE;

namespace XnaDesignerGenerator
{
    public class ObjectServiceListConverter : TypeListConverter
    {
        public ObjectServiceListConverter()
            : base(typeof(Microsoft.Xna.Framework.DrawableGameComponent).GetInterfaces())
        {
        }

        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
                return true;
            return base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
            {
                return Type.GetType(value.ToString());
            }
            return base.ConvertFrom(context, culture, value);
        }

        private void AnalyseCodeElement(CodeElement ce,string ns,IList classes,Type iface)
        {
            if (ce is CodeNamespace)
                ns += ce.FullName + ".";
            if (ce is CodeClass)
            {
                Type type = Type.GetType(ns + ce.Name);
                if(iface.IsAssignableFrom(type) && !type.IsInterface)
                    classes.Add(Type.GetType(ns + ce.Name));
            }
            if(ce is CodeNamespace && ((CodeNamespace)ce).Members!=null)
            {
                foreach (CodeElement c in ((CodeNamespace)ce).Members)
                    AnalyseCodeElement(c, ns,classes,iface);
            }
        }

        public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            IList result = new ArrayList();
            XnaGameService component = (XnaGameService)context.Instance;
            TypeConverter.StandardValuesCollection svc = base.GetStandardValues(context);
            if (component.Assembly != null && component.ServiceInterface!=null && component.Project==null)
            {
                foreach (Module module in component.Assembly.GetModules())
                {
                    foreach (Type type in module.GetTypes())
                    {
                        if(component.ServiceInterface.IsAssignableFrom(type) && !type.IsInterface)
                            result.Add(type);
                    }
                }
            }
            if (component.Project != null && component.ServiceInterface!=null)
            {
                try
                {
                    foreach (object o in component.Project.ProjectItems)
                    {
                        ProjectItem projectItem = (ProjectItem)o;
                        if (projectItem.FileCodeModel != null)
                        {
                            if (projectItem.FileCodeModel.CodeElements != null)
                            {
                                foreach (CodeElement ce in projectItem.FileCodeModel.CodeElements)
                                {
                                    AnalyseCodeElement(ce, "", result,component.ServiceInterface);
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message + "\n" + e.StackTrace, e.GetType().FullName);
                }
            }
            return new StandardValuesCollection(result);
        }

        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return false;
        }


    }
}
